Skip to content

feat(2d): globalCompositeOperation takes the blend modes, multiply to luminosity, where the server has RENDER 0.11 - #567

Merged
sidorares merged 3 commits into
masterfrom
feat/blend-composite-ops
Nov 9, 2026
Merged

sidorares merged 3 commits into
masterfrom
feat/blend-composite-ops

Conversation

@sidorares

@sidorares sidorares commented Nov 9, 2026 •

Copy link
Copy Markdown
Owner

The 2d context mapped only the Porter-Duff names and lighter to XRender operators, and ignored every other name, so multiply, screen and the rest read back as whatever the op was before and drew as it. RENDER 0.11 has all fifteen, Multiply to HSLLuminosity, and every X.Org server since 2009 answers 0.11: Xorg, Xvfb, Xwayland, XQuartz.

The context now takes a blend mode's name only where the server answered QueryVersion with 0.11 or later. A server below it raises BadPictOp for these after the call has returned, so reading the name back stays the way a caller finds out whether it will be drawn. react-x11-components' <Html> asks exactly that before it paints mix-blend-mode with one, and on X11 it found none: vercel.com's footer draws a gray pill over its "New" badges with multiply, which drew as source-over and hid the word.

The blend operators are mask-bounded, beside Over and the rest: a transparent source leaves the destination as it was through every one of them, and each is linear in the source, so a clip and globalAlpha folded into the mask come to what they would after the op. A path of scattered pieces is masked as its pieces, as for source-over.

The setter and _op look a name up as an own property now, so toString and constructor are no longer names it takes.

test/blend-modes.test.js holds every mode to what Xvfb drew for an opaque colour over an opaque one, through fillRect, fillRects, a path, a stroke, text and a surface drawn whole, scaled and turned, under globalAlpha and a path clip, and checks the names below 0.11. docs/context-2d.md has a section on them, with two things about real servers: glamor composites them in software, and Debian bookworm's pixman, 0.42.2, masks green twice and blue not at all for the four HSL modes, which 0.46.4 does not. node-x11's CI found the second.

x11's floor moves to ^4.4.0, the release with sidorares/node-x11#318, whose in-process server composites the blend operators. Up to 4.3.3 it answered 0.11 and raised BadPictOp for every one, so against it the new test failed 42 times over, and an ntk taking the names on top of it would have handed every suite drawing on that server a BadPictOp for each. The whole suite passes against the published 4.4.0.

… luminosity, where the server has RENDER 0.11

The context mapped only the Porter-Duff names and lighter to XRender
operators and ignored the rest, so a blend mode read back as the op before
and drew as it. RENDER 0.11 has all fifteen, and every X.Org server since
2009 answers 0.11. A name is taken only where the server did, since one
below it raises BadPictOp after the call has returned: reading the name
back is how a caller knows it will be drawn.

The blend operators are mask-bounded: a transparent source leaves the
destination as it was, and each is linear in the source, so a clip and
globalAlpha folded into the mask come to what they would after the op.

Needs an x11 whose in-process server composites them.
@sidorares
sidorares marked this pull request as ready for review November 9, 2026 12:20
@sidorares
sidorares merged commit 6b265c1 into master Nov 9, 2026
7 checks passed
@sidorares
sidorares deleted the feat/blend-composite-ops branch November 9, 2026 12:21
sidorares pushed a commit that referenced this pull request Nov 9, 2026
🤖 I have created a release *beep* *boop*
---


## [8.29.0](v8.28.0...v8.29.0)
(2026-11-09)


### Features

* **2d:** globalCompositeOperation takes the blend modes, multiply to
luminosity, where the server has RENDER 0.11
([#567](#567))
([6b265c1](6b265c1))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant